<html>
<head><meta charset="utf-8"><title>Portable SIMD Compiler Support · t-compiler · Zulip Chat Archive</title></head>
<h2>Stream: <a href="https://rust-lang.github.io/zulip_archive/stream/131828-t-compiler/index.html">t-compiler</a></h2>
<h3>Topic: <a href="https://rust-lang.github.io/zulip_archive/stream/131828-t-compiler/topic/Portable.20SIMD.20Compiler.20Support.html">Portable SIMD Compiler Support</a></h3>

<hr>

<base href="https://rust-lang.zulipchat.com">

<head><link href="https://rust-lang.github.io/zulip_archive/style.css" rel="stylesheet"></head>

<a name="213847415"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/131828-t-compiler/topic/Portable%20SIMD%20Compiler%20Support/near/213847415" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Lokathor <a href="https://rust-lang.github.io/zulip_archive/stream/131828-t-compiler/topic/Portable.20SIMD.20Compiler.20Support.html#213847415">(Oct 19 2020 at 21:17)</a>:</h4>
<p>Hello all. I'm here on behalf of the Portable SIMD Project. We're investigating the best way to implement the Portable SIMD API's internals.</p>
<p>Currently we're using <code>repr(simd)</code>, some of the <code>simd_foo</code> intrinsics when available (eg: <code>simd_add</code>, <code>simd_mul</code>, etc), and also directly linking to LLVM intrinisics when a particular <code>simd_foo</code> doesn't exist. The complication is that the Cranelift project is getting to closer to being a usable backend for Rust, and directly calling LLVM intrinsics doesn't work with Cranelift. We're currently going to continue implementing and developing the API using LLVM, but we want to get a plan for where the project will be moving in the longer term.</p>
<p>The current best idea is that if vector support was moved into the MIR layer, then the MIR could be lowered into appropriate codegen IR during the normal lowering process. Any vector operations that don't exist on a target platform can be converted to standard scalar operations on each lane, as if the vector was an array instead. Rust code would access the MIR vector ops via rustc intrinsics, without directly relying on a particular codegen backend.</p>
<p>This would also potentially allow both MIR optimizations and MIRI to work with vectors as well, always a good bonus.</p>
<p>So what I'm asking you is: Given that yall actually work on the compiler, does this sound like a good plan? Or would some other approach be better?</p>



<a name="213855354"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/131828-t-compiler/topic/Portable%20SIMD%20Compiler%20Support/near/213855354" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Joshua Nelson <a href="https://rust-lang.github.io/zulip_archive/stream/131828-t-compiler/topic/Portable.20SIMD.20Compiler.20Support.html#213855354">(Oct 19 2020 at 22:38)</a>:</h4>
<p><span class="user-mention" data-user-id="133247">@bjorn3</span> would be the one to ask about how this interacts with cranelift</p>



<a name="213855403"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/131828-t-compiler/topic/Portable%20SIMD%20Compiler%20Support/near/213855403" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Joshua Nelson <a href="https://rust-lang.github.io/zulip_archive/stream/131828-t-compiler/topic/Portable.20SIMD.20Compiler.20Support.html#213855403">(Oct 19 2020 at 22:39)</a>:</h4>
<p>and maybe <span class="user-mention" data-user-id="211727">@Jonas Schievink</span> or <span class="user-mention" data-user-id="123586">@nagisa</span> for mir-opts and codegen</p>



<a name="213855649"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/131828-t-compiler/topic/Portable%20SIMD%20Compiler%20Support/near/213855649" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Jonas Schievink  [he/him] <a href="https://rust-lang.github.io/zulip_archive/stream/131828-t-compiler/topic/Portable.20SIMD.20Compiler.20Support.html#213855649">(Oct 19 2020 at 22:42)</a>:</h4>
<p>Hmm, so does this basically propose to copy the SIMD-related LLVM intrinsics you're currently using into rustc? That doesn't seem terrible, but it means that we have to essentially duplicate them (or at least their signature).</p>



<a name="213855928"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/131828-t-compiler/topic/Portable%20SIMD%20Compiler%20Support/near/213855928" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Jonas Schievink  [he/him] <a href="https://rust-lang.github.io/zulip_archive/stream/131828-t-compiler/topic/Portable.20SIMD.20Compiler.20Support.html#213855928">(Oct 19 2020 at 22:46)</a>:</h4>
<p>Or do you want first-class support for SIMD operations in MIR itself?</p>



<a name="213857615"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/131828-t-compiler/topic/Portable%20SIMD%20Compiler%20Support/near/213857615" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Lokathor <a href="https://rust-lang.github.io/zulip_archive/stream/131828-t-compiler/topic/Portable.20SIMD.20Compiler.20Support.html#213857615">(Oct 19 2020 at 23:06)</a>:</h4>
<p>We'd need first class support for SIMD within MIR <em>or</em> we'd need some other system for using <code>cfg</code> to use LLVM or Cranelift intrinsic linking during compilation based on codegen system used.</p>
<p>Simulacrum and others indicated that using <code>cfg</code> to detect Cranelift or LLVM would probably be a poor solution, and I agree. So we're hoping that we can get full SIMD support into MIR. Then the <em>source code</em> for SIMD would be codegen unaware, and only rustc would think about how different codegen backends interact with SIMD.</p>



<a name="213857705"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/131828-t-compiler/topic/Portable%20SIMD%20Compiler%20Support/near/213857705" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Lokathor <a href="https://rust-lang.github.io/zulip_archive/stream/131828-t-compiler/topic/Portable.20SIMD.20Compiler.20Support.html#213857705">(Oct 19 2020 at 23:07)</a>:</h4>
<p>Though, if all simd operations can be done as rustc intrinisics <em>without</em> affecting MIR that's fine too I guess.</p>



<a name="213857712"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/131828-t-compiler/topic/Portable%20SIMD%20Compiler%20Support/near/213857712" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Jonas Schievink  [he/him] <a href="https://rust-lang.github.io/zulip_archive/stream/131828-t-compiler/topic/Portable.20SIMD.20Compiler.20Support.html#213857712">(Oct 19 2020 at 23:07)</a>:</h4>
<p>I'm not sure why you'd need SIMD operations in MIR for that, it seems to me that rustc intrinsics could do that job just fine</p>



<a name="213857783"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/131828-t-compiler/topic/Portable%20SIMD%20Compiler%20Support/near/213857783" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Jonas Schievink  [he/him] <a href="https://rust-lang.github.io/zulip_archive/stream/131828-t-compiler/topic/Portable.20SIMD.20Compiler.20Support.html#213857783">(Oct 19 2020 at 23:08)</a>:</h4>
<p>That would allow us to keep almost everything unchanged, except that we lift the LLVM intrinsics you need to rustc intrinsics, and add a mapping to LLVM intrinsics to <code>rustc_codegen_llvm</code></p>



<a name="213858181"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/131828-t-compiler/topic/Portable%20SIMD%20Compiler%20Support/near/213858181" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Lokathor <a href="https://rust-lang.github.io/zulip_archive/stream/131828-t-compiler/topic/Portable.20SIMD.20Compiler.20Support.html#213858181">(Oct 19 2020 at 23:14)</a>:</h4>
<p>I don't fully recall why we landed on MIR. Looking back at <a href="#narrow/stream/257879-project-portable-simd/topic/Portable.20pure-Rust.20implementation">the conversation here</a>, it seems like <span class="user-mention" data-user-id="125270">@scottmcm</span> proposed the MIR part of things.</p>



<a name="213863467"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/131828-t-compiler/topic/Portable%20SIMD%20Compiler%20Support/near/213863467" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> scottmcm <a href="https://rust-lang.github.io/zulip_archive/stream/131828-t-compiler/topic/Portable.20SIMD.20Compiler.20Support.html#213863467">(Oct 20 2020 at 00:26)</a>:</h4>
<p>I don't think we necessarily need first-class MIR support; intrinsics are probably sufficient.  (Though maybe some of the basics would make sense in mir, like having MIR's <code>+</code> support vector types too.)</p>
<p>IIRC the core of the MIR idea was that it could be nice to do the "scalarize" step in MIR so it would be usable across backends and targets.  It's possible that doing it in the cranelift backend would also be fine.</p>



<a name="213863569"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/131828-t-compiler/topic/Portable%20SIMD%20Compiler%20Support/near/213863569" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Jonas Schievink  [he/him] <a href="https://rust-lang.github.io/zulip_archive/stream/131828-t-compiler/topic/Portable.20SIMD.20Compiler.20Support.html#213863569">(Oct 20 2020 at 00:28)</a>:</h4>
<p>I see, yeah that makes sense. I don't think there's too much of a benefit of having the MIR-level operators work with vectors, but we could still write a MIR pass that scalarizes the intrinsic calls.</p>



<a name="213863918"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/131828-t-compiler/topic/Portable%20SIMD%20Compiler%20Support/near/213863918" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> scottmcm <a href="https://rust-lang.github.io/zulip_archive/stream/131828-t-compiler/topic/Portable.20SIMD.20Compiler.20Support.html#213863918">(Oct 20 2020 at 00:33)</a>:</h4>
<p>(Or maybe just replace the intrinsic calls with <code>compiler-builtin</code> calls -- I don't remember what the linking details for compiler-builtins are.)</p>



<a name="213918871"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/131828-t-compiler/topic/Portable%20SIMD%20Compiler%20Support/near/213918871" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> nagisa <a href="https://rust-lang.github.io/zulip_archive/stream/131828-t-compiler/topic/Portable.20SIMD.20Compiler.20Support.html#213918871">(Oct 20 2020 at 13:32)</a>:</h4>
<p>what is an example of a vector operation that is not supported and would require scalar conversion when lowering to llvm-ir?</p>



<a name="213918933"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/131828-t-compiler/topic/Portable%20SIMD%20Compiler%20Support/near/213918933" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> nagisa <a href="https://rust-lang.github.io/zulip_archive/stream/131828-t-compiler/topic/Portable.20SIMD.20Compiler.20Support.html#213918933">(Oct 20 2020 at 13:32)</a>:</h4>
<p>scalarizing some of the ops (shuffles for instance) can be non-trivial</p>



<a name="213918940"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/131828-t-compiler/topic/Portable%20SIMD%20Compiler%20Support/near/213918940" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Jonas Schievink  [he/him] <a href="https://rust-lang.github.io/zulip_archive/stream/131828-t-compiler/topic/Portable.20SIMD.20Compiler.20Support.html#213918940">(Oct 20 2020 at 13:32)</a>:</h4>
<p>None, but Cranelift might require this</p>



<a name="213961129"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/131828-t-compiler/topic/Portable%20SIMD%20Compiler%20Support/near/213961129" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Jubilee <a href="https://rust-lang.github.io/zulip_archive/stream/131828-t-compiler/topic/Portable.20SIMD.20Compiler.20Support.html#213961129">(Oct 20 2020 at 18:32)</a>:</h4>
<p>Basically we want a situation where the relative amount of support that a codegen backend offers for actually doing the codegen we want does not have to affect our API in a visible fashion and also does not block those codegen backends from being added. Then if LLVM, or even Cranelift, supports something the other doesn't, we can just go ahead and use it internally to rustc. Making the commits to scalarize what we need scalarized is OK, we're actually pretty ready to do that, but we will need to develop a framework for doing so.</p>



<a name="213961916"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/131828-t-compiler/topic/Portable%20SIMD%20Compiler%20Support/near/213961916" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Jubilee <a href="https://rust-lang.github.io/zulip_archive/stream/131828-t-compiler/topic/Portable.20SIMD.20Compiler.20Support.html#213961916">(Oct 20 2020 at 18:39)</a>:</h4>
<p>Ops on a SIMD vector are morally equivalent to manipulations on an array once you politely ignore the vector register and instead treat it as something that should be handled in a normal fashion by scalar registers. There's some sneaky tricks that you can do actually, with a scalar register, that make it imitate a vector register, but we're looking for a basic abstraction boundary more than anything, so any such silliness would not be in scope of this initial step.</p>



<a name="213972873"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/131828-t-compiler/topic/Portable%20SIMD%20Compiler%20Support/near/213972873" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Lokathor <a href="https://rust-lang.github.io/zulip_archive/stream/131828-t-compiler/topic/Portable.20SIMD.20Compiler.20Support.html#213972873">(Oct 20 2020 at 20:07)</a>:</h4>
<p>Because they were mentioned, I'll note that the shuffle ops in scalar code are actually fairly simple. You just form a new array from the old array, and you're done.</p>



<a name="213996872"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/131828-t-compiler/topic/Portable%20SIMD%20Compiler%20Support/near/213996872" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> nagisa <a href="https://rust-lang.github.io/zulip_archive/stream/131828-t-compiler/topic/Portable.20SIMD.20Compiler.20Support.html#213996872">(Oct 21 2020 at 00:46)</a>:</h4>
<p>Well it might not have been element-wise shuffle specifically, but I distinctly remember triggering scalar fallback for a single vector LLVM DAG instruction and it generated a couple dozen pages of scalar code.</p>



<a name="213996882"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/131828-t-compiler/topic/Portable%20SIMD%20Compiler%20Support/near/213996882" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> nagisa <a href="https://rust-lang.github.io/zulip_archive/stream/131828-t-compiler/topic/Portable.20SIMD.20Compiler.20Support.html#213996882">(Oct 21 2020 at 00:46)</a>:</h4>
<p>don't remember what exactly it was tho</p>



<a name="213996999"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/131828-t-compiler/topic/Portable%20SIMD%20Compiler%20Support/near/213996999" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> nagisa <a href="https://rust-lang.github.io/zulip_archive/stream/131828-t-compiler/topic/Portable.20SIMD.20Compiler.20Support.html#213996999">(Oct 21 2020 at 00:48)</a>:</h4>
<p>and ultimately when considering the complexity of such a functionality, the lowering of the complicated instructions is exactly what matters, not obvious/trivial things like pairwise multiply or, I guess, shuffle (which is just shuffle of virtual registers, indeed)</p>



<a name="213997039"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/131828-t-compiler/topic/Portable%20SIMD%20Compiler%20Support/near/213997039" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> nagisa <a href="https://rust-lang.github.io/zulip_archive/stream/131828-t-compiler/topic/Portable.20SIMD.20Compiler.20Support.html#213997039">(Oct 21 2020 at 00:49)</a>:</h4>
<p>So thinking about it, it is entirely unclear to me if MIR is at all an appropriate place for such lowerings. It does not have any knowledge about the target machine for one, with the exception of its datalayout.</p>



<a name="213997184"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/131828-t-compiler/topic/Portable%20SIMD%20Compiler%20Support/near/213997184" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> nagisa <a href="https://rust-lang.github.io/zulip_archive/stream/131828-t-compiler/topic/Portable.20SIMD.20Compiler.20Support.html#213997184">(Oct 21 2020 at 00:51)</a>:</h4>
<p>not entirely clear what it should do if target machine were to support a specific instruction after some legalization (dropping down to scalar code in that case would be a pessimisation, but trying to figure this out in MIR also seems wrong; and hard too)</p>



<a name="213997272"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/131828-t-compiler/topic/Portable%20SIMD%20Compiler%20Support/near/213997272" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> nagisa <a href="https://rust-lang.github.io/zulip_archive/stream/131828-t-compiler/topic/Portable.20SIMD.20Compiler.20Support.html#213997272">(Oct 21 2020 at 00:52)</a>:</h4>
<p>But I do concur that having MIR _understand_ vector operations is useful – it would at very least be a prerequisite for const-evaluation of simd code, I think?</p>



<a name="214110283"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/131828-t-compiler/topic/Portable%20SIMD%20Compiler%20Support/near/214110283" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Jubilee <a href="https://rust-lang.github.io/zulip_archive/stream/131828-t-compiler/topic/Portable.20SIMD.20Compiler.20Support.html#214110283">(Oct 21 2020 at 20:27)</a>:</h4>
<p>Alright, so<br>
1) adding vectors to MIR might be a good idea for various reasons,<br>
2) but as a place to provide a scalar lowering it doesn't seem to make sense.</p>
<p>Mmm, do you have any recommendations on next steps then? We need the ability to furnish a pure Rust scalar lowering <em>somewhere</em> that a codegen backend can opt to use if necessary.</p>



<a name="214126120"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/131828-t-compiler/topic/Portable%20SIMD%20Compiler%20Support/near/214126120" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> nagisa <a href="https://rust-lang.github.io/zulip_archive/stream/131828-t-compiler/topic/Portable.20SIMD.20Compiler.20Support.html#214126120">(Oct 21 2020 at 23:07)</a>:</h4>
<p>If we resort to doing this in rustc code it'd have to live in the lowering-to-backend code, there isn't really anywhere else for it to be as rustc's job ends after that step. But to achieve best bang-for-buck it'd be better for it to live in the layer that generates assembly, pretty much.</p>



<hr><p>Last updated: Aug 07 2021 at 22:04 UTC</p>
</html>